﻿namespace Microsoft.ServiceModel.DomainServices.Tools
{
    using System;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.ServiceModel.DomainServices;

    internal static class DbContextUtilities
    {
        private static Type _dbContextTypeReference;
        private const string DatabaseTypeName = "System.Data.Entity.Database";
        internal const string DbContextTypeName = "System.Data.Entity.DbContext";
        private const string IDatabaseInitializerTypeName = "System.Data.Entity.IDatabaseInitializer`1";

        public static bool CompareWithSystemType(Type type, string systemTypeFullName)
        {
            if ((type == null) || string.IsNullOrEmpty(systemTypeFullName))
            {
                return false;
            }
            string fullName = type.FullName;
            if (type.IsGenericType)
            {
                fullName = type.GetGenericTypeDefinition().FullName;
            }
            if (!fullName.Equals(systemTypeFullName))
            {
                return false;
            }
            if (!type.Assembly.IsSystemAssembly())
            {
                return false;
            }
            return true;
        }

        public static Type GetDbContextTypeReference(Type contextType)
        {
            if (((_dbContextTypeReference == null) && !contextType.IsInterface) && !contextType.IsValueType)
            {
                for (Type type = contextType; (type != null) && (type != typeof(object)); type = type.BaseType)
                {
                    if (CompareWithSystemType(type, "System.Data.Entity.DbContext"))
                    {
                        _dbContextTypeReference = type;
                        break;
                    }
                }
            }
            return _dbContextTypeReference;
        }

        public static bool IsDbContext(this Type type)
        {
            if (_dbContextTypeReference != null)
            {
                return _dbContextTypeReference.IsAssignableFrom(type);
            }
            return (GetDbContextTypeReference(type) != null);
        }

        public static Type LoadTypeFromAssembly(Assembly assembly, string typeName)
        {
            Type type = null;
            if (assembly != null)
            {
                type = assembly.GetType(typeName, false, false);
            }
            return type;
        }

        internal static void ResetDbContextTypeReference()
        {
            _dbContextTypeReference = null;
        }

        public static void SetDbInitializer(Type contextType, Type dbContextTypeReference, object initializer)
        {
            if ((contextType != null) && (dbContextTypeReference != null))
            {
                Type type = LoadTypeFromAssembly(dbContextTypeReference.Assembly, "System.Data.Entity.Database");
                if (type != null)
                {
                    Type type2 = dbContextTypeReference.Assembly.GetType("System.Data.Entity.IDatabaseInitializer`1");
                    if ((type2 != null) && type2.IsGenericType)
                    {
                        type2 = type2.MakeGenericType(new Type[] { dbContextTypeReference });
                        MethodInfo method = type.GetMethod("SetInitializer", new Type[] { type2 });
                        if ((method != null) && method.IsGenericMethod)
                        {
                            MethodInfo info2 = method.MakeGenericMethod(new Type[] { contextType });
                            if (info2 != null)
                            {
                                info2.Invoke(null, new object[] { initializer });
                            }
                        }
                    }
                }
            }
        }

        public static Type DbContextTypeReference
        {
            get
            {
                return _dbContextTypeReference;
            }
        }
    }
}

